package top.healthylife.gateway.core.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import top.healthylife.basics.utils.utils.R;
import top.healthylife.gateway.core.config.SystemInit;
import top.healthylife.gateway.dto.annotation.SystemInfoField;
import top.healthylife.gateway.dto.request.base.SystemInfoDto;
import top.heathylife.gateway.common.po.ApiParameterPo;
import top.heathylife.gateway.common.po.ParentApiPo;
import top.heathylife.gateway.common.po.SystemPo;
import top.heathylife.gateway.common.vo.ApiReqRestVo;

import java.lang.reflect.ParameterizedType;
import java.net.URLDecoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 获取服务的系统参数解释
 * @author maoxiaomeng
 */
@Api(tags = "获取服务的系统参数解释")
@Slf4j
@RestController
@AllArgsConstructor
public class SystemController {

    @ApiOperation("获取服务的系统参数解释")
    @GetMapping
    public R<List<SystemInfoDto>> index() {
        List<SystemInfoDto> collect = Arrays.stream(SystemInit.getSystemClass().getDeclaredFields())
                .filter(e -> e.isAnnotationPresent(SystemInfoField.class))
                .map(e -> {
                    SystemInfoField a = e.getAnnotation(SystemInfoField.class);
                    SystemInfoDto o = new SystemInfoDto().setCls(e.getType()).setName(e.getName()).setInfo(a.value());
                    if (a.next()) {
                        List<SystemInfoDto> voList = Arrays.stream(((Class) ((ParameterizedType) e.getGenericType()).getActualTypeArguments()[0]).getDeclaredFields())
                                .map(v -> new SystemInfoDto().setCls(v.getType()).setName(v.getName()).setInfo(v.getAnnotation(SystemInfoField.class).value())).collect(Collectors.toList());
                        o.setVos(voList);
                    }
                    return o;
                })
                .collect(Collectors.toList());
        return R.ok(collect);
    }

    @SneakyThrows
    @ApiOperation("获取接口入参与出参")
    @GetMapping("/api")
    public R<ApiReqRestVo> api(@RequestParam String apiName) {
        apiName = URLDecoder.decode(apiName, "utf-8");
        //根据名称获取入参泛型
        List<ApiParameterPo> apiReqParameters = SystemInit.getParameter(SystemInit.getReqDto(apiName));
        List<ApiParameterPo> apiReturnParameters = SystemInit.getFields(SystemInit.getResultDto(apiName)).getList();
        ParentApiPo parentApiPo = SystemInit.getParentApiPoMap().get(apiName);
        // 将树形结构的参数转为单列集合
        ApiReqRestVo apiReqRestVo = BeanUtil.copyProperties(parentApiPo, ApiReqRestVo.class)
                .setApiReq(apiReqParameters)
                .setApiResult(apiReturnParameters);
        return R.ok(apiReqRestVo);
    }

//    @SneakyThrows
//    @Log
//    @ApiOperation("获取接口入参与出参,屏蔽无关的参数")
//    @GetMapping("/api/available/params/")
//    public R<ApiReqRestVo> apiAvailableParams(@RequestParam String apiName) {
//        apiName = URLDecoder.decode(apiName, "utf-8");
//        //根据名称获取入参泛型
//
//        List<ApiParameterPo> apiReturnParameters = SystemInit.getFields(SystemInit.getResultDto(apiName)).getList();
//        ParentApiPo parentApiPo = SystemInit.getParentApiPoMap().get(apiName);
//        // 将树形结构的参数转为单列集合
//        ApiReqRestVo apiReqRestVo = BeanCopyUtil.copy(parentApiPo, ApiReqRestVo.class)
//                .setApiResult(apiReturnParameters);
//        return R.ok(apiReqRestVo);
//    }


    @SneakyThrows
    @ApiOperation("模糊检索API返回参数")
    @GetMapping("/search")
    public R search(@RequestParam String searchName) {
        searchName = URLDecoder.decode(searchName, "utf-8");
        SystemPo systemPo = SystemInit.getSystemPo();
        String shortName = systemPo.getShortName();
        //根据名称获取出参泛型
        Map<String, List<ApiParameterPo>> listMap = SystemInit.getApiReturnParameters();

        List<ApiPriceDto> collect = new ArrayList<>();
        //搜索有问题
        for (String apiName : listMap.keySet()) {
            List<ApiParameterPo> apiParameterPos = listMap.get(apiName);
            String finalSearchName1 = searchName;
            //获取价格,
            //暂时只做外面这一层,其它的不做,子层暂时不支持数据获取
            List<ApiParameterPo> list1 = searchField(apiParameterPos, finalSearchName1);
            List<ApiPriceDto> list = list1.stream()
                    //获取价格,
                    //暂时只做外面这一层,其它的不做,子层暂时不支持数据获取
                    .map(e -> new ApiPriceDto()
                            .setApiName(apiName)
                            .setShortName(shortName)
                            .setInfo(e.getInfo())
                            .setKey(e.getKey())
                            .setReference(e.getExample())
                            .setType(e.getTypeName())
                            .setAbsoluteKey(e.getAbsoluteKey())
                    )
                    .collect(Collectors.toList());
            collect.addAll(list);
        }
        return R.ok(collect);
    }

    private List<ApiParameterPo> searchField(List<ApiParameterPo> apiParameterPos, String finalSearchName) {
        return searchField(apiParameterPos, finalSearchName, null);
    }

    private List<ApiParameterPo> searchField(List<ApiParameterPo> apiParameterPos, String finalSearchName, List<ApiParameterPo> apiParams) {
        if (ObjectUtil.isNull(apiParams)) {
            apiParams = new ArrayList<>();
        }
        for (ApiParameterPo apiParameterPo : apiParameterPos) {
            List<ApiParameterPo> childList = apiParameterPo.getList();
            if (apiParameterPo.getList() == null) {
                String info = Optional.ofNullable(apiParameterPo.getInfo()).orElse("");
                if (info.contains(finalSearchName)) {
                    apiParams.add(apiParameterPo);
                }
                continue;
            }
            searchField(childList, finalSearchName, apiParams);
        }
        return apiParams;
    }


    @Data
    @Accessors(chain = true)
    @ApiModel("API的价格对象")
    public static class ApiPriceDto {
        @ApiModelProperty("第三方接口名称")
        String shortName;
        @ApiModelProperty("接口名称")
        String apiName;
        @ApiModelProperty("属性名")
        String key;
        @ApiModelProperty(required = true, value = "属性全路径名,包含了接口所在类的层级,\".\"号分割")
        String absoluteKey;
        @ApiModelProperty(value = "参数解释")
        String info;
        @ApiModelProperty("示例")
        String reference;
        @ApiModelProperty("类型")
        String type;
        @ApiModelProperty("接口的访问介个,单位:分")
        Long price;
    }

}
